#include "xcustomchart.h"
#include <QLineSeries>
#include <QtCharts>
#include <QtCore/QtMath>
#include <QDebug>

XCustomChart::XCustomChart(QGraphicsItem* parentItem)
    :QChart(parentItem)
    ,clicked(false)
{

}

XCustomChart::~XCustomChart()
{

}

void XCustomChart::slot_clickOnPoint(const QPointF& ptSeries)   //获取曲线句柄
{
    clicked=false;
    series=qobject_cast<QLineSeries*>(sender());    //获取鼠标单击的系列
    getNearestPoint(ptSeries);  //取得离ptSeries最近的点
}

void XCustomChart::setModifyFlag(bool b)    //设置修改标志
{
    clicked=b;
}

void XCustomChart::getNearestPoint(const QPointF& ptSeries)  //获取最近的点
{
    ptNew=QPointF();
    const auto points=series->points();

    if(clicked) //正在修改曲线
    {
        auto itePoint = points.begin();
        for(;itePoint!=points.end();itePoint++)
        {
            if((itePoint+1)==points.end())  //最后一个点
            {
                ptNew=*itePoint;
                ptNew.setY(ptSeries.y());   //用鼠标位置处的Y值替换
                break;
            }
            else if(fabs((*itePoint).x()-ptSeries.x())<fabs((*(itePoint+1)).x()-ptSeries.x()))
            {//修改中间的点Y值为当前鼠标位置
                ptNew=*itePoint;
                ptNew.setY(ptSeries.y());
                break;
            }
        }
    }
    else    //鼠标在曲线上刚按下，找最近的点
    {
        for(QPointF point : points)
        {
            //遍历找最近点
            if(distanceOf(point,ptSeries)<distanceOf(ptNew,ptSeries))
            {
                ptNew=point;    //最近点
                clicked=true;   //置标志
            }
        }
    }
}

qreal XCustomChart::distanceOf(const QPointF& point1, const QPointF& point2) //获取两点距离
{
    //勾股定律求两点距离
    return qSqrt((point1.x()-point2.x())*(point1.x()-point2.x())+
                 (point1.y()-point2.y())*(point1.y()-point2.y()));
}

void XCustomChart::modifyCurve(const QPoint& ptInView)   //修改指定点处的曲线
{
    if(!clicked)
    {
        return;
    }
    //将视图坐标映射为系列坐标
    QPointF ptLast=ptNew;
    QPointF ptInSeries;
    //把当前点坐标系改为系列坐标系
    if(!map2Series(ptInView,ptInSeries)){
        return;
    }
    qDebug()<<ptNew<<ptInView<<ptInSeries;
    //找到离系列坐标最近的点
    getNearestPoint(ptInSeries);
    //斜率插值
    QPointF ptStart;
    QPointF ptEnd;
    if(ptLast.x()>ptNew.x())
    {
        ptStart=ptNew;
        ptEnd=ptLast;
    }
    else
    {
        ptStart=ptLast;
        ptEnd=ptNew;
    }
    const auto points = series->points();
    //斜线：y=kx+b
    qreal k=(ptEnd.y()-ptStart.y())/(ptEnd.x()-ptStart.x());
    qreal b=ptStart.y()-k*ptStart.x();
    //遍历所有坐标点，找到位于两点之间的数据，替换
    for(QPointF point:points)
    {
        if((point.x()>=ptStart.x())&&(point.x()<=ptEnd.x()))
        {
            series->replace(point,QPointF(point.x(),k*point.x()+b));
        }
    }
    //更新坐标
    ptNew=ptInSeries;
}

bool XCustomChart::map2Series(const QPoint& ptInView, QPointF& ptInSeries) const
{
    QAbstractAxis* axisx=this->axisX();
    QValueAxis* haxis=nullptr;
    if(axisx->type()==QAbstractAxis::AxisTypeValue)
    {
        haxis=qobject_cast<QValueAxis*>(axisx);
    }
    QAbstractAxis* axisy=this->axisY();
    QValueAxis* vaxis=nullptr;
    if(axisy->type()==QAbstractAxis::AxisTypeValue)
    {
        vaxis=qobject_cast<QValueAxis*>(axisy);
    }
    if(!haxis || !vaxis)
    {
        return false;
    }
    //首先计算坐标轴上单位坐标的像素宽度
    qreal xUnit=(plotArea().width())/(haxis->max()-haxis->min());
    qreal yUnit=(plotArea().height())/(vaxis->max()-vaxis->min());
    //先将视图坐标转换为图表坐标
    QPointF ptChart;
    ptChart.setX(ptInView.x()-plotArea().x());
    ptChart.setY(ptInView.y()-plotArea().y());
    //再将图表坐标转换为系列坐标
    qreal x=ptChart.x()/xUnit;
    qreal y=vaxis->max()-ptChart.y()/yUnit;
    ptInSeries=QPointF(x,y);
    return true;
}
